/*
 * Jenny Ruppen 09-730-391
 * Sebastien Goldberg 08-914-855
 * Henry Raymond 08-928-061
 * Stefan Mussato 09-752-270
 */
 
package ch.uzh.ifi.sopra.gruppe9.game;

import java.util.ArrayList;

import com.jme3.scene.Node;


/**
 * Draws a selection to the GUI and manages it.
 */
public class GuiSelection extends Node {
	
	
	/**
	 * List of all selection options.
	 */
	private ArrayList<GuiSelectionOption> options = new ArrayList<GuiSelectionOption>();
	
	
	/**
	 * List of all registered mouseOver event elements which are the selection options.
	 */
	private ArrayList<IMouseOverable> mouseOverables = new ArrayList<IMouseOverable>();
	
	
	/**
	 * List of all registered click event elements which are the selection options.
	 */
	private ArrayList<IClickable> clickables = new ArrayList<IClickable>();
	
	
	/**
	 * True if no selection is allowed.
	 */
	private boolean allowZeroSelections;
	
	
	/**
	 * True if multiple selections are allowed.
	 */
	private boolean allowMultipleSelections;
	
	
	/**
	 * Currently selected value (if only one selection is allowed).
	 */
	private int value = -1;
	
	
	/**
	 * Currently selected values (if multiple selections are allowed).
	 */
	private ArrayList<Integer> values = new ArrayList<Integer>();
	
	
	/**
	 * Callback function which is called when the selection changes.
	 */
	private ICallback action = null;
	
	
	/**
	 * Constructor
	 */
	public GuiSelection(boolean allowZeroSelections, boolean allowMultipleSelections) {
		this.allowZeroSelections = allowZeroSelections;
		this.allowMultipleSelections = allowMultipleSelections;
	}
	
	
	/**
	 * Sets initial selection if only one selection is allowed.
	 */
	public void setInitialValue(int newValue) {
		if(allowMultipleSelections) {
			ArrayList<Integer> oldValues = new ArrayList<Integer>();
			oldValues.addAll(values);
			for(int oldValue : oldValues) {
				removeValue(oldValue);
			}
		} else {
			removeValue(value);
		}
		addValue(newValue);
	}
	
	
	/**
	 * Sets if multiple options can be selected at the same time.
	 */
	public void allowMultipleSelections(boolean allowMultipleSelections) {
		this.allowMultipleSelections = allowMultipleSelections;
	}


	/**
	 * Sets initial selection if several selections are allowed.
	 */
	public void setInitialValues(ArrayList<Integer> newValues) {
		ArrayList<Integer> oldValues = new ArrayList<Integer>();
		oldValues.addAll(values);
		for(int oldValue : oldValues) {
			removeValue(oldValue);
		}
		for(int newValue : newValues) {
			addValue(newValue);
		}
	}
	
	
	/**
	 * Add selection option.
	 */
	public void addOption(int value, GUI.Offset offset, int positionX, int positionY, int width, int height, int zIndex) {
		GuiSelectionOption newOption = new GuiSelectionOption(this, value, offset, positionX, positionY, width, height, zIndex);
		options.add(newOption);
		mouseOverables.add(newOption);
		clickables.add(newOption);
		this.attachChild(newOption);
	}
	
	
	/**
	 * Clear current selection.
	 */
	public void clearSelection() {
		ArrayList<Integer> oldValues = new ArrayList<Integer>();
		oldValues.addAll(values);
		for(int oldValue : oldValues) {
			removeValue(oldValue);
		}
		removeValue(value);
	}
		
		
	/**
	 * Add option to selected values.
	 */
	public void addValue(Integer newValue) {
		int oldValue = -1;
		if(allowMultipleSelections) {
			values.add(newValue);
		} else {
			oldValue = value;
			value = newValue;
		}
		for(GuiSelectionOption option : options) {
			if(option.getValue() == oldValue) {
				option.setSelected(false);
			}
			if(option.getValue() == newValue) {
				option.setSelected(true);
			}
		}
		if(action != null) {
			action.run();
		}
	}
		
	
	/**
	 * Remove option from selected values.
	 */
	public void removeValue(Integer oldValue) {
		if(oldValue == -1) {
			return;
		}
		if(allowMultipleSelections) {
			values.remove(oldValue);
		} else {
			if(!allowZeroSelections) {
				return;
			}
			value = -1;
		}
		for(GuiSelectionOption option : options) {
			if(option.getValue() == oldValue) {
				option.setSelected(false);
			}
		}
		if(action != null) {
			action.run();
		}
	}
	
	
	/**
	 * Remove all selected values.
	 */
	public void removeAllValues() {
		for(GuiSelectionOption option : options) {
			option.setSelected(false);
		}
		value = -1;
		values.clear();
		if(action != null) {
			action.run();
		}
	}
	
	
	/**
	 * Deactivate value
	 */
	public void deactivate(int inactiveValue) {
		if(value == inactiveValue) {
			value = -1;
		}
		for(Integer listValue : values) {
			if(listValue == inactiveValue) {
				values.remove(listValue);
			}
		}
		for(GuiSelectionOption option : options) {
			if(option.getValue() == inactiveValue) {
				option.deactivate();
			}
		}
		if(action != null) {
			action.run();
		}
	}
	
	
	/**
	 * Activate value
	 */
	public void activate(int inactiveValue) {
		for(GuiSelectionOption option : options) {
			if(option.getValue() == inactiveValue) {
				option.activate();
			}
		}	
	}
	
	
	/**
	 * Activate all values
	 */
	public void activateAll() {
		for(GuiSelectionOption option : options) {
			option.activate();
		}	
	}
	
	
	/**
	 * Deactivate all values
	 */
	public void deactivateAll() {
		removeAllValues();
		for(GuiSelectionOption option : options) {
			option.deactivate();
		}	
	}
	
	
	/**
	 * Set callback function which is called when the selection changes.
	 */
	public void setAction(ICallback action) {
		this.action = action;
	}


	/**
	 * Get selected value if only one selection is allowed.
	 */
	public int getValue() {
		return value;
	}


	/**
	 * Get selected values if several selections are allowed.
	 */
	public ArrayList<Integer> getValues() {
		return values;
	}
	
	
	/**
	 * Get all mouseOverable elements of this selection.
	 */
	public ArrayList<IMouseOverable> getMouseOverables() {
		return mouseOverables;
	}
	
	
	/**
	 * Get all clickable elements of this selection.
	 */
	public ArrayList<IClickable> getClickables() {
		return clickables;
	}
	
	
}
